package edu.xlh.travel.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import edu.xlh.travel.common.Result;
import edu.xlh.travel.dao.ScoreDetailDao;
import edu.xlh.travel.enumeration.ScoreRuleEnum;
import edu.xlh.travel.enumeration.ScoreSourceEnum;
import edu.xlh.travel.pojo.*;
import edu.xlh.travel.pojo.querypojo.QueryScoreDetail;
import edu.xlh.travel.service.ForeHotelOrderService;
import edu.xlh.travel.service.OrdersService;
import edu.xlh.travel.service.ScoreDetailService;
import edu.xlh.travel.service.TotalScoreService;
import edu.xlh.travel.util.DateTimeUtil;
import edu.xlh.travel.util.IdWorker;
import edu.xlh.travel.util.PageResult;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Service
@Transactional
public class ScoreDetailServiceImpl implements ScoreDetailService {
    @Autowired
    private ScoreDetailDao scoreDetailDao;
    @Autowired
    private ForeHotelOrderService foreHotelOrderService;

    @Autowired
    private IdWorker idWorker;
    @Autowired
    private TotalScoreService totalScoreService;

    @Lazy
    @Autowired
    private OrdersService ordersService;

    @Override
    public void addScoreDetails(ScoreDetail scoreDetail) {
        scoreDetailDao.save(scoreDetail);
    }

    @Override
    public void scoreOperation(String userId , Integer qty) {
        //TODO 根据用户id获取积分总表唯一对应的id，存在即是加入了vip才有积分操作，应该有个if
        TotalScore totalScoreEntity = totalScoreService.findByUserId(userId);
        if (totalScoreEntity != null) {
            ScoreDetail scoretDetaile = new ScoreDetail();
            scoretDetaile
                    .setTotalScoreId(totalScoreEntity.getId())
                    .setUserId(userId)
                    .setCreateTime(new Date())
                    .setModifyTime(new Date());
            //总分
            int totalScore = 0;
            System.out.println(new Date());
            //1.每次下单3笔
            Integer nOfeveryTimeYouPlaceAnOrder = Integer.
                    parseInt(ScoreRuleEnum.nOfeveryTimeYouPlaceAnOrder.getCode());
            if (qty >= nOfeveryTimeYouPlaceAnOrder) {
                scoretDetaile.setId(idWorker.nextId() + "");
                int s = qty / nOfeveryTimeYouPlaceAnOrder;
                int y = qty % nOfeveryTimeYouPlaceAnOrder;
                //记录总分，计算公式：有几个3笔*设置的分数+余数
                totalScore = Integer.parseInt(ScoreRuleEnum.everyTimeYouPlaceAnOrderQtyMetaScore.getCode())*s + y;
                scoretDetaile.setScore(String.valueOf(totalScore));
                scoretDetaile.setSourceCode(ScoreSourceEnum.moreThanNAtATime.getCode());
                scoretDetaile.setSourceDesc(ScoreSourceEnum.moreThanNAtATime.getDesc());
                scoretDetaile.setUserName(totalScoreEntity.getUserName());
                //生成明细
                addScoreDetails(scoretDetaile);
            }


            //2.每次下单，加2分
            scoretDetaile.setId(idWorker.nextId() + "");
            scoretDetaile.setScore(ScoreRuleEnum.everyTimeYouPlaceAnOrderMetaScore.getCode());
            scoretDetaile.setSourceCode(ScoreSourceEnum.everyTimeYouPlaceAnOrder.getCode());
            scoretDetaile.setSourceDesc(ScoreSourceEnum.everyTimeYouPlaceAnOrder.getDesc());
            scoretDetaile.setUserName(totalScoreEntity.getUserName());
            scoretDetaile.setDelFlag("0");
            //生成明细
            addScoreDetails(scoretDetaile);
            Integer everyTimeYouPlaceAnOrderMetaScore =
                    Integer.parseInt(ScoreRuleEnum.everyTimeYouPlaceAnOrderMetaScore.getCode());
            //更新总分
            totalScore += everyTimeYouPlaceAnOrderMetaScore;



            //3.历史超过3笔，本次叠加积分公式:超出的部分的订单总数*元分数*n+qty，
            //获取历史订单个数-景点
            int scenicOrderNum = ordersService.countByUserId(userId);
            //获取历史订单个数-酒店
            int hotelOrderNum = foreHotelOrderService.countByUserId(userId);
            //景点+酒店
            int totalOrderNum = scenicOrderNum + hotelOrderNum;
            //历史订单下单够3笔
            Integer nOfhistoryOrderNTimes =
                    Integer.parseInt(ScoreRuleEnum.nOfhistoryOrderNTimes.getCode());
            //int conutOrderNumPassTwo  = totalOrderNum / nOfhistoryOrderNTimes;
            //统计次数，历史总订单超过3笔,计算公式：超出的部分*设置的分数+本次订单数量
            if (totalOrderNum >= nOfhistoryOrderNTimes) {
                Integer historyOrderNTimes = Integer.parseInt(ScoreRuleEnum.historyOrderNTimesMetaScore.getCode());
                Integer score = (totalOrderNum - nOfhistoryOrderNTimes) * historyOrderNTimes + qty;
                scoretDetaile.setId(idWorker.nextId() + "");
                scoretDetaile.setScore(String.valueOf(score));
                scoretDetaile.setSourceCode(ScoreSourceEnum.orderNTimes.getCode());
                scoretDetaile.setSourceDesc(ScoreSourceEnum.orderNTimes.getDesc());
                scoretDetaile.setUserName(totalScoreEntity.getUserName());
                //生成明细
                addScoreDetails(scoretDetaile);
                //更新总分
                totalScore += score;
            }

            //TODO 查询该用户所有的积分明细，下单够8次的额外加分，
            //TODO 记录总分2=记录总分1+每次下单+总订单2的倍数，更新总表
            totalScoreService.updateTotalScoreByUserId(totalScoreEntity.getId() ,  totalScore);
        }
    }

   /* @Override
    public Result findScoreDetailByUserId(ScoreDetail scoreDetail, HttpSession session) {
        User user = (User)session.getAttribute("admin");
        if (user == null) {
            return new Result(201 , "会话过期，请重新登录");
        }
        String userId = scoreDetail.getUserId();
        List<ScoreDetail> scoreDetailList =  scoreDetailDao.findByUserId(userId);
        if (scoreDetailList != null)  {
            return new Result(200 , "积分详情查询成功"  , scoreDetailList);
        }
        return new Result(202 , "积分详情查询失败");
    }*/

    @Override
    public Result findAllScoreDetail(int page, int limit, String userId, HttpSession session) {
        User user = (User)session.getAttribute("admin");
        if (user == null) {
            return new Result(201);
        }
        Sort sort = Sort.by(Sort.Direction.DESC, "modifyTime");
        Pageable pageable= PageRequest.of(page-1,limit ,sort);
        Specification specification = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> scoreDetailList = new ArrayList<>();
                scoreDetailList.add(criteriaBuilder.equal(root.get("userId"), userId));
                return criteriaBuilder.and(scoreDetailList.toArray(new Predicate[scoreDetailList.size()]));
            }
        };
        Page<ScoreDetail> scoreDetailsPage = scoreDetailDao.findAll(specification , pageable);
        if (scoreDetailsPage!=null) {
            return new Result(0 , "积分详情分页数据获取成功" , new PageResult<ScoreDetail>(scoreDetailsPage.getTotalElements(), scoreDetailsPage.getContent()));
        }
        return new Result(201, "积分详情分页数据获取失败");
    }

    @Override
    public Result findScoreDetailByUserId(int page  , int limit , String userId, HttpSession session) {
        User user = (User)session.getAttribute("admin");
        if (user == null) {
            return new Result(201);
        }

        Specification specification = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> scoreDetailList = new ArrayList<>();
                scoreDetailList.add(criteriaBuilder.equal(root.get("delFlag"), "0"));
                scoreDetailList.add(criteriaBuilder.equal(root.get("userId"), userId));
                return criteriaBuilder.and(scoreDetailList.toArray(new Predicate[scoreDetailList.size()]));
            }
        };
        Sort sort = Sort.by(Sort.Direction.DESC, "modifyTime");
        Pageable pageable= PageRequest.of(page-1,limit ,sort);
        Page<ScoreDetail> scoreDetailPage = scoreDetailDao.findAll(specification, pageable);
        if (scoreDetailPage!=null) {
            return new Result(0 , "积分详情查询成功" , new PageResult<ScoreDetail>(scoreDetailPage.getTotalElements(), scoreDetailPage.getContent()));
        }
        return new Result(200 , "积分详情查询失败");
    }

    @Override
    public Result batchDelete(JSONArray jsonArray, HttpSession session) {
        List<ScoreDetail> scoreDetailList = JSON.parseArray(jsonArray.toJSONString() , ScoreDetail.class);
        try {
            scoreDetailList.stream().iterator().forEachRemaining(scoreDetail -> {
                scoreDetailDao.updateScoreDetailDelFlagByScoreDetailId(scoreDetail.getId() , "1");
            });
        }catch (Exception e) {
            return new Result(201);
        }
        return new Result(200);
    }

    @Override
    public Result deleteById(String id, HashMap hashMap, HttpSession session) {
        User user = (User)session.getAttribute("admin");
        if (user == null) {
            return new Result(201,"会话过期，请重新登陆");
        }
        String scoreDetailId = (String) hashMap.get("id");
        if (id.equals(scoreDetailId)) {
            try {
                scoreDetailDao.updateScoreDetailDelFlagByScoreDetailId(scoreDetailId , "1");
            } catch (Exception e) {
                return new Result(201 , "id为"+scoreDetailId+"的积分详情记录"+"删除失败");
            }
        } else {
            return new Result(202 , "id为"+scoreDetailId+"的积分详情id有问题");
        }
        return new Result(200 , "id为"+scoreDetailId+"的积分详情记录"+"删除成功");
    }

    @Override
    public Result QueryScoreDetailByCondition(Integer page, Integer limit, QueryScoreDetail queryScoreDetail, HttpSession session) {
        User userFromSession = (User)session.getAttribute("admin");
        if (userFromSession == null) {
            return new Result(201,"会话过期，请重新登陆");
        }

        Specification specification = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> scoreDetailList = new ArrayList<>();
                if (StringUtils.isNotEmpty(queryScoreDetail.getUserName())) {
                    scoreDetailList.add(criteriaBuilder.like(root.get("userName") , "%" + queryScoreDetail.getUserName() + "%"));
                }
                if (StringUtils.isNotEmpty(queryScoreDetail.getSourceCode())) {
                    scoreDetailList.add(criteriaBuilder.equal(root.get("sourceCode") , queryScoreDetail.getSourceCode()));
                }
                if (queryScoreDetail.getCreateTime() != null) {
                    String crateTime = DateTimeUtil.dateToStr(queryScoreDetail.getCreateTime(), "yyyy-MM-dd");
                    String crateTimeStartTimeToStr = crateTime + " " + "00:00:00";
                    String crateTimeEndTimeToStr = crateTime + " " + "23:59:59";
                    Date crateTimeStartTimeToDate = DateTimeUtil.strToDate(crateTimeStartTimeToStr , "yyyy-MM-dd HH:mm:ss");
                    Date crateTimeEndTimeToDate = DateTimeUtil.strToDate(crateTimeEndTimeToStr , "yyyy-MM-dd HH:mm:ss");
                    scoreDetailList.add(criteriaBuilder.between(root.get("createTime") ,  crateTimeStartTimeToDate , crateTimeEndTimeToDate));
                }

                return criteriaBuilder.and(scoreDetailList.toArray(new Predicate[scoreDetailList.size()]));
            }
        };
        Pageable pageable= PageRequest.of(page-1,limit);
        Page<ScoreDetail> scoreDetailListPage  = scoreDetailDao.findAll(specification , pageable);
        if (scoreDetailListPage!=null) {
            return new Result(0 , "积分详情分页数据获取成功" , new PageResult<ScoreDetail>(scoreDetailListPage.getTotalElements(), scoreDetailListPage.getContent()));
        }
        return new Result(201 , "积分详情列表失败");
    }

    @Override
    public Result sign(HttpSession session) {
        User user = (User)session.getAttribute("user");
        if (user == null) {
            return new Result(201,"会话过期，请重新登陆");
        }
        Specification specification = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> scoreDetailList = new ArrayList<>();
                if (StringUtils.isNotEmpty(user.getId())) {
                    scoreDetailList.add(criteriaBuilder.equal(root.get("userId") , user.getId()));
                }
                String crateTime = DateTimeUtil.dateToStr(new Date(), "yyyy-MM-dd");
                String crateTimeStartTimeToStr = crateTime + " " + "00:00:00";
                String crateTimeEndTimeToStr = crateTime + " " + "23:59:59";
                Date crateTimeStartTimeToDate = DateTimeUtil.strToDate(crateTimeStartTimeToStr , "yyyy-MM-dd HH:mm:ss");
                Date crateTimeEndTimeToDate = DateTimeUtil.strToDate(crateTimeEndTimeToStr , "yyyy-MM-dd HH:mm:ss");
                scoreDetailList.add(criteriaBuilder.between(root.get("createTime") ,  crateTimeStartTimeToDate , crateTimeEndTimeToDate));

                scoreDetailList.add(criteriaBuilder.equal(root.get("sourceCode") , ScoreSourceEnum.signIn.getCode()));
                return criteriaBuilder.and(scoreDetailList.toArray(new Predicate[scoreDetailList.size()]));
            }
        };
        List list = scoreDetailDao.findAll(specification);
        if (list != null && list.size()>0) {
            return new Result(200 , "今天已经签到过了");
        }
        TotalScore byUserId = totalScoreService.findByUserId(user.getId());
        ScoreDetail scoreDetail1 = new ScoreDetail().setId(idWorker.nextId() + "")
                .setDelFlag("0")
                .setUserId(user.getId())
                .setUserName(user.getName())
                .setScore(ScoreRuleEnum.signInMetaScore.getCode())
                .setSourceCode(ScoreSourceEnum.signIn.getCode())
                .setSourceDesc(ScoreSourceEnum.signIn.getDesc())
                .setCreateTime(new Date())
                .setModifyTime(new Date())
                .setTotalScoreId(byUserId.getId());
        try {
            scoreDetailDao.save(scoreDetail1);
            totalScoreService.updateTotalScoreByUserId(byUserId.getId() , Integer.valueOf(ScoreRuleEnum.signInMetaScore.getCode()));
        } catch (Exception e) {
            return new Result(201 , "签到失败");
        }
        return new Result(200 , "签到成功，获取" + ScoreRuleEnum.signInMetaScore.getCode() +"积分" , Integer.parseInt(ScoreRuleEnum.signInMetaScore.getCode()) + Integer.parseInt(byUserId.getTotalScore()));
    }
}
